#ifndef AST_H_
#define AST_H_

//for asprintf()
#define _GNU_SOURCE
#include <stdio.h>

#include "language_scanner.h"
#include "tokens.h"
#include "../hash/ght_hash_table.h"

typedef enum _node_op {
	top=0,//root the node by itself has no value, only an array of children
	double_const=OP_DOUBLE_CONST,//unary
	integer_const=OP_INTEGER_CONST,//unary
	label=OP_LABEL,//unary
	add=OP_ADD,//binary
	sub=OP_SUB,//binary
	mul=OP_MUL,//binary
	divide=OP_DIV,//binary
	assignment=OP_ASSIGN,//binary
	print=OP_PRINT,//unary
	math_expr=OP_MATH_EXPR//unary (used for math expressions consisting of math expressions,
			//like when they're generated by parenthesis)
} AST_node_op;
typedef enum _node_assoc {
	none,left,right
} AST_assoc_type;
typedef enum _ast_node_type {
	root,unary,binary,chain
} AST_node_type;

struct _AST_node;

typedef union _AST_node_value {
	struct root {
		char *filename;
		ght_hash_table_t *variables;
	} root;
	struct unary {
		token_value *val;//label, double_const, integer_const
	} unary;
	struct chain {//for chaining math_expr'essions, like a math_expr surrounded by parenthesis
		struct _AST_node *val;
	} chain;
	struct binary {
		struct _AST_node *left;
		struct _AST_node *right;
	} binary;//add,sub,mul.divide,assignment
} AST_node_value;

typedef struct _AST_node {
	AST_node_op op;
	AST_assoc_type assoc;
	AST_node_type type;//unary or binary
	struct _AST_node **ancestors;//array of roots, this way we can have any level of nestednesses
	size_t ancestors_len;
	struct _AST_node **children;//immediate children statements, top statements and alike
	size_t children_len;
	//TODO: siblings?
	AST_node_value val;
} AST_node;

AST_node* ast_malloc_node(AST_node_op op,AST_assoc_type assoc,AST_node_type type);
AST_node* ast_dup_node(AST_node *node); 
int	ast_push_ancestor(AST_node *node,AST_node *ancestor);
AST_node* ast_pop_ancestor(AST_node *node);
int	ast_add_child(AST_node *node,AST_node *child);
int	ast_free_node(AST_node *node);
char*	ast_serialize_node(AST_node *node);

#endif
